﻿#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>


//联合体和枚举

//一；联合体（共同体）

//1.1联合体类型的声明
//和结构体一样，联合体也是由一个或多个成员组成，这样的成员可以是不同类型
//但编译器只为最大的成员分配足够的空间，联合体的特点是所有成员共用一块内存空间
//所以也叫共同体



//！！！注；给联合体中一个成员赋值，其他成员的值也会发生变化
//用union来声明联合体
//union un
//{
//	char c1;//1
//	int i;//4
//};
//
//int main()
//{
//	union un z;
//	printf("%zd", sizeof(z));//4
//	z.i = 0x11223344;
//	z.c1 = 0x55;
//	//观察联合体内存的变化
//
//	return 0;
//}


//1.2；联合体的特点
//联合体的成员是共用同一块内存空间的，这样一个联合体变量的大小至少是最大成员的大小
//（因为至少得有能力保存最大的那个成员)

//1.3相同成员的结构体和联合体的对比
//struct s
//{
//	char c1;
//	int i;
//};
//union un
//{
//	char c1;
//	int i;
//};
//int main()
//{
//	printf("%zd\n", sizeof(struct s));//8
//	printf("%zd\n", sizeof(union un));//4
// //画图可以更直观的了解区别
//	return 0;
//}





//1.4联合体大小的计算
//联合体的大小至少是最大成员的大小
//当最大成员大小不是最大对齐数的整数倍时，就要对齐到最大对齐数的整数倍
//union un
//{
//	char arr[5];//大小是5，最大成员
//	//但它的对齐数是1，因为这是字符数组，一个字符大小是1，按数组元素来确定对齐数
//	int i;//大小是4，对齐数就是4
//};
//
//int main()
//{
//	printf("%zd", sizeof(union un));//8
//	//char arr[5]大小是5，int i大小是4，所以arr是最大成员。但最大对齐数是4
//	//所以要对齐到最大对齐数的整数倍，就是8.
//	return 0;
//}






//联合体的应用举例


//⽐如，我们要搞⼀个活动，要上线⼀个礼品兑换单，礼品兑换单中有三种商品：！！！图书、杯⼦、衬衫！！！。
//每⼀种商品！！！都有：库存量、价格、商品类型！！！和商品类型相关的其他信息。
//图书：书名、作者、⻚数
//杯⼦：设计
//衬衫：设计、可选颜⾊、可选尺⼨

//只用结构体的方式
//struct gift_list
//{
//	int kc;//库存
//	double price;//价格
//	int type;//商品类型
//
//	char name[20];//书名
//	char author[20];//作者
//	int num;//页数
//
//	char design[20];//设计
//	int color;//可选颜色
//	int sizes;//尺寸
//
//};
//这样确实可以，但是不是所有成员我们都有用，比如商品是图书时，design，color sizes都没用到
//但是还是会占用内存，所以这边我们可以用联合体，把公共的属性列出来，商品本身特殊的属性用联合体
//这样商品是图书是，其他属性就不会占用内存，可以节省内存空间

//用结构体
//struct gift_list
//{
//	int kc;//库存
//	double price;//价格
//	int type;//商品类型
//	
//	union
//	{
//		struct
//		{
//			char name[20];
//			char authoe[20];
//			int num;
//		} book;//变量是图书
//
//		struct
//		{
//			char design[20];
//		}cup;//变量是杯子
//		struct
//		{
//			char design[20];
//			int color;
//			int sizes;
//		}shirt;//变量是衬衫
//	}item;//项目
//
//};//这里联合体是联合体中的结构体都是匿名，因为这里只需要创建一次变量






//二；枚举类型

//2.1枚举的声明
//枚举顾名思义就是—列举，把可能的取值一一列举
//比如生活中；一周星期一 — 星期五，只可能是这几天
//性别；只可能是男或女，月份；1月—12月，这些都可以一一列举

//enum sex  //enum声明枚举类型
//{
//	man,//用逗号！！！
//	woman,
//
//	//枚举常量（记住是常量，所以不能更改）
//};
//enum sex 就是枚举类型
//！枚举常量都是有值的，默认第一位是0，依次递增1，在声明类型的时候也可以赋值
//
//enum day
//{
//	
//	Monday = 1,
//	Tusday = 2,
//	Wednesday = 3,
//	Thursday = 4,
//	Friday = 5,
//	Saturday = 6,
//	Sunday = 7,
//	//！这不是在修改它，而是给它一个应的值，比如后面1就代表了Monday！
//};



//2.2；枚举的有点
//我们也可以用#define定义常量，为什么要用枚举呢
//1；增加代码的可读性和可维护性
//2；和#define定义的标识符比较，枚举有类型检查，更严谨
//3；便于测试，预处理阶段会删除#define定义的符号
//4；使用方便，一次可以定义多个常量
//2；枚举常量是遵循作用域规则的，枚举声明在函数内，只能在函数内使用